#pragma once

#include <iostream>
#include <string>
#include <time.h>   // time()
#include <stdarg.h> // va_start(), va_arg(), va_end()
#include <fstream>

using std::string;


bool is_savelog = true;
const char* logname = "log.txt";

enum Level
{
    DEBUG = 0,
    INFO,
    WARNING,
    ERROR,
    FATAL
};


string LevelToString(int level)
{
    switch (level)
    {
    case 0:
        return "DEBUG"; break;
    case 1:
        return "INFO"; break;
    case 2:
        return "WARNING"; break;
    case 3:
        return "ERROR"; break;
    case 4:
        return "FATAL"; break;
    
    default:
        return "None"; break;
    }
}

string CurrentTimeString()
{
    time_t second = time(nullptr);
    struct tm* format_time = localtime(&second);
    if(format_time == nullptr) { return "None"; }

    char time_buffer[1024];
    snprintf(time_buffer, sizeof(time_buffer), "%4d-%2d-%2d %2d:%2d:%2d", 
            format_time->tm_year + 1900,
            format_time->tm_mon + 1,
            format_time->tm_mday,
            format_time->tm_hour,
            format_time->tm_min,
            format_time->tm_sec);
    return time_buffer;
}

bool SaveToFile(const char* logname, const string& message)
{
    std::ofstream out(logname, std::ios::app);
    if(!out.is_open()) { return false; }
    out << message << '\n';
    out.close();
    return true;
}

void LogMessage(std::string filename, int line, int level, bool is_save, const char* format, ...)
{
    string level_s = LevelToString(level);
    string time_s = CurrentTimeString();

    va_list arg;
    va_start(arg, format);

    char mess_buffer[1024];
    vsnprintf(mess_buffer, sizeof(mess_buffer), format, arg);
    va_end(arg);

    string message = "[" + time_s + "]" + "[" + level_s + "]" + 
            "[" + mess_buffer + "]"+ "(<" + filename + "> =" + std::to_string(line) + "=)";
    if(!is_save) { std::cout << message << std::endl; return; }
    
    if(!SaveToFile(logname, message))
    {
        std::cout << "Write into txt break error !" << std::endl;
    }
}

// DEBUG = 0,INFO,WARNING,ERROR,FATAL
#define Log(level, format, ...) \
    do \
    { \
        LogMessage(__FILE__, __LINE__, level, is_savelog, format, ##__VA_ARGS__); \
    }while(0)


